using Engine;
using Game;
using GameEntitySystem;
using TemplatesDatabase;

namespace SCIENEW {
    public class ComponentFireBox : ComponentInventoryBase, IUpdateable, IFireBoxComponent {
        public UpdateOrder UpdateOrder => UpdateOrder.Default;
        protected float m_fireTimeRemaining;
        protected float m_heatLevel;
        protected float m_fireTime;
        public float m_speed = 1f;
        public float HeatLevel => m_heatLevel;
        public float FireTimeRemaining => m_fireTimeRemaining;

        public float FireTime => m_fireTime;

        public SubsystemTerrain m_subsystemTerrain;

        public SubsystemExplosions m_subsystemExplosions;

        public ComponentBlockEntity m_componentBlockEntity;

        public override int GetSlotCapacity(int slotIndex, int value) {
            return BlocksManager.Blocks[Terrain.ExtractContents(value)].GetFuelHeatLevel(value) > 0f ? base.GetSlotCapacity(slotIndex, value) : 0;
        }

        public override void Load(ValuesDictionary valuesDictionary, IdToEntityMap idToEntityMap) {
            base.Load(valuesDictionary, idToEntityMap);
            m_fireTimeRemaining = valuesDictionary.GetValue("FireTimeRemaining", 0f);
            m_heatLevel = valuesDictionary.GetValue("HeatLevel", 0f);
            m_fireTime = valuesDictionary.GetValue("FireTime", 0f);
            m_subsystemTerrain = Project.FindSubsystem<SubsystemTerrain>(true);
            m_subsystemExplosions = Project.FindSubsystem<SubsystemExplosions>(true);
            m_componentBlockEntity = Entity.FindComponent<ComponentBlockEntity>(true);
        }

        public override void Save(ValuesDictionary valuesDictionary, EntityToIdMap entityToIdMap) {
            base.Save(valuesDictionary, entityToIdMap);
            valuesDictionary.SetValue("FireTimeRemaining", m_fireTimeRemaining);
            valuesDictionary.SetValue("HeatLevel", m_heatLevel);
            valuesDictionary.SetValue("FireTime", m_fireTime);
        }

        public void Update(float dt) {
            if (m_fireTimeRemaining <= 0f) //没有燃烧时间了
            {
                if (m_heatLevel > 0) m_heatLevel = 0; //无燃烧时间，燃料等级归零
                if (GetSlotCount(0) > 0) //燃料添加逻辑
                {
                    int value = GetSlotValue(0);
                    Block block = BlocksManager.Blocks[Terrain.ExtractContents(value)];
                    if (block.GetExplosionPressure(value) > 0f) {
                        m_slots[0].Count--;
                        m_subsystemExplosions.TryExplodeBlock(m_componentBlockEntity.Coordinates.X, m_componentBlockEntity.Coordinates.Y, m_componentBlockEntity.Coordinates.Z, value);
                    }
                    if (block.GetFuelFireDuration(value) > 0) //放入的是正确的燃料，并且水量大于0
                    {
                        m_fireTime = block.GetFuelFireDuration(value);
                        m_fireTimeRemaining = block.GetFuelFireDuration(value);
                        m_heatLevel = block.GetFuelHeatLevel(value);
                        m_slots[0].Count--;
                    }
                }
            }
            else //有燃烧时间
            {
                m_fireTimeRemaining = MathUtils.Max(0, m_fireTimeRemaining - dt);
            }

            ReplaceFurnace(m_componentBlockEntity.Coordinates);
        }

        public virtual void ReplaceFurnace(Point3 coordinates) {
            TerrainChunk chunkAtCell = m_subsystemTerrain.Terrain.GetChunkAtCell(coordinates.X, coordinates.Z);
            if (chunkAtCell != null
                && chunkAtCell.State == TerrainChunkState.Valid) {
                int cellValue = m_subsystemTerrain.Terrain.GetCellValue(coordinates.X, coordinates.Y, coordinates.Z);
                int direction = IlluminableDevice.GetDirection_Static(cellValue);
                int deviceValue = DevicesBlockManager.GetDeviceValueByType(typeof(FireBoxDevice), m_heatLevel > 0 ? 0b100 | direction : direction);
                m_subsystemTerrain.ChangeCell(coordinates.X, coordinates.Y, coordinates.Z, deviceValue);
            }
        }

        public bool IsPreheating() => m_heatLevel > 0;
    }
}